#include "stdafx.h"
#include "Utility.h"
#include "WatchDir.h"

HANDLE hChangeEvent; 

UINT WaitForVolumeChange(LPVOID pParam)
{
    ThreadParam* p = static_cast<ThreadParam*> (pParam);

    CStringArray arBaseVolumeList;

    if(GetVolumesList(arBaseVolumeList))
    {
        int nBaseCount = arBaseVolumeList.GetCount();
        
        GetListOfCDorDVD(arBaseVolumeList);
        GetValidVolumes(arBaseVolumeList);

        int nBaseValidCount = arBaseVolumeList.GetCount();

        hChangeEvent = CreateEvent( NULL,              
                                    TRUE,               
                                    FALSE,              
                                    TEXT("ChangeEvent")); 

        while(TRUE)
        {
            Sleep(100);

            CStringArray arNewVolumeList;

            GetVolumesList(arNewVolumeList);

            int nNewCount = arNewVolumeList.GetCount();

            if(nNewCount != nBaseCount)
            {
                ::SendMessage(p->mDlg, MYMESS_CALL_VOLCOUNT_CHANGE, 0, 0);
                
                SetEvent(hChangeEvent);

                nBaseCount = nNewCount;
            }
            
            GetListOfCDorDVD(arNewVolumeList);
            GetValidVolumes(arNewVolumeList);

            int nNewValidCount = arNewVolumeList.GetCount();

            if(nNewValidCount != nBaseValidCount)
            {
                Sleep(500);

                ::SendMessage(p->mDlg, MYMESS_CALL_VOL_CHANGE, 0, 0);
                SetEvent(hChangeEvent);

                nBaseValidCount = nNewValidCount;
            }
        }
    }
    
    delete p;

    CloseHandle(hChangeEvent);

    return 0;
}

UINT WaitForDirectoryChange(LPVOID pParam)
{
    ThreadParam* p = static_cast<ThreadParam*> (pParam);

    CStringArray arVolumesList;

    if(!GetVolumesList(arVolumesList))
    {
        delete p;
        return 0;
    }

    if(!GetValidVolumes(arVolumesList))
    {
        delete p;
        return 0;
    }

    int nValidVolumesCount = arVolumesList.GetCount();

    while(TRUE)
    {
        HANDLE* dwChangeHandles = new HANDLE[nValidVolumesCount+1]; 

        for(int i=0; i < nValidVolumesCount; ++i)
        {
            dwChangeHandles[i] = FindFirstChangeNotification(   arVolumesList[i],// directory to watch 
                TRUE,// do not watch subtree 
                FILE_NOTIFY_CHANGE_FILE_NAME |
                FILE_NOTIFY_CHANGE_DIR_NAME); // watch file name changes 

            if (dwChangeHandles[i] == INVALID_HANDLE_VALUE) 
            {
                FindCloseChangeNotification(dwChangeHandles[i]);

                for(int j = 0; j < i; ++j)
                {
                    FindCloseChangeNotification(dwChangeHandles[j]);
                }

                delete [] dwChangeHandles;
                delete p;
                return 0;
            }
        }

        dwChangeHandles[nValidVolumesCount] = hChangeEvent;

        while (TRUE) 
        {

            DWORD dwWaitStatus = WaitForMultipleObjects(nValidVolumesCount+1, dwChangeHandles, FALSE, INFINITE); 

            for(int i = 0; i < nValidVolumesCount; ++i)
            {
                if(dwWaitStatus == WAIT_OBJECT_0 + i)
                {
                    ::SendMessage(p->mDlg, MYMESS_CALL_DIR_CHANGE, i, 0);

                    if(FindNextChangeNotification(dwChangeHandles[i]) == FALSE)
                    {
                        for(int j = 0; j< nValidVolumesCount; ++j)
                        {
                            FindCloseChangeNotification(dwChangeHandles[j]);
                        }

                        delete [] dwChangeHandles;
                        delete p;
                        return 0;
                    }
                }
            }

            if(dwWaitStatus == WAIT_OBJECT_0 + nValidVolumesCount)
            {
                if(!GetVolumesList(arVolumesList))
                {
                    delete p;
                    return 0;
                }

                if(!GetValidVolumes(arVolumesList))
                {
                    delete p;
                    return 0;
                }

                ResetEvent(hChangeEvent);

                for(int j = 0; j< nValidVolumesCount; ++j)
                {
                    FindCloseChangeNotification(dwChangeHandles[j]);
                }

                nValidVolumesCount = arVolumesList.GetCount();

                delete [] dwChangeHandles;

                break;
            }
        }
    }

    delete p;
    return 0;
}